/*
 * Alex Rodrigo de Oliveira - 06/30403
 * Danilo Gaby Andersen Trindade - 06/82039
 * 
 * Detecção de erros de 2 bits
 */


/*Bibliotecas incluidas*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

#define BITS_SIZE 4 /*Tamanho de bits na mensagem*/
#define CORROMPER 2 /*Quantidade de bits a corromper*/


int main(void) {

	char *vet;
	char x[2], y[2], d[2];  // CRC pros eixos X e Y e cópia da diagonal
	bool errx, erry;	// diz se teve erro nas linhas e nas colunas
	int *corromper, corrompido = 0;

	srand(time(NULL)); /*Muda o seed do random*/

	vet = (char*) malloc(BITS_SIZE * sizeof(char));

	/*Gera bits aleatorios*/
	puts("\nBits Originais:");
	for (int i = 0; i < BITS_SIZE; i++) {
		vet[i] = (rand() % 2);
		printf("%d ", vet[i]);
	}

	/* Calcula o CRC pros bits */
	x[0] = vet[0] ^ vet[1];
	x[1] = vet[2] ^ vet[3];
	y[0] = vet[0] ^ vet[2];
	y[1] = vet[1] ^ vet[3];
	d[0] = vet[0];
	d[1] = vet[3];

	/*Gera corrompimento de bits aleatorios*/
	corromper = (int*) malloc(CORROMPER * sizeof(int));
	for (int i = 0; i < CORROMPER; i++) {
		do {
			corrompido = 1;
			corromper[i] = (rand() % BITS_SIZE);
			for (int j = 0; j < i; j++) {
				if (corromper[j] == corromper[i]) {
					corrompido = 0;
				}
			}
		} while (!corrompido);
	}

	/*Mostra os bits que serao corrompidos*/
	printf("\n\nBits a corromper: %d, %d\n\n", (BITS_SIZE - corromper[0] - 1),
			(BITS_SIZE - corromper[1] - 1));


	/*Corrompe os bits*/
	for (int i = 0; i < CORROMPER; i++) {
		if (vet[corromper[i]] == 0) {
			vet[corromper[i]] = 1;
		} else {
			vet[corromper[i]] = 0;
		}
	}

	/*Mostra vetor final apos corrompimento*/
	puts("Bits Apos Corrompimento:");
	for (int i = 0; i < BITS_SIZE; i++) {
		printf("%d ", vet[i]);
	}
	puts("\n");

	/* Encontra erros nas linhas e colunas */
	if (x[0] != (vet[0] ^ vet[1])) {
		errx = true;
	} else {
		errx = false;
	}
	if (y[0] != (vet[0] ^ vet[2])) {
		erry = true;
	} else {
		erry = false;
	}

	/* Corrige os erros */
	if (errx) {
		if (d[0] != vet[0]) {
			puts("Erro no bit 3.");
			vet[0] = (vet[0] == 0) ? 1 : 0;
		} else {
			puts("Erro no bit 2.");
			vet[1] = (vet[1] == 0) ? 1 : 0;
		}
		if (d[1] != vet[3]) {
			puts("Erro no bit 0.");
			vet[3] = (vet[3] == 0) ? 1 : 0;
		} else {
			puts("Erro no bit 1.");
			vet[2] = (vet[2] == 0) ? 1 : 0;
		}
	} else if (erry) {
		if (d[0] != vet[0]) {
			puts("Erro no bit 3.");
			vet[0] = (vet[0] == 0) ? 1 : 0;
		} else {
			puts("Erro no bit 1.");
			vet[2] = (vet[2] == 0) ? 1 : 0;
		}
		if (d[1] != vet[3]) {
			puts("Erro no bit 0.");
			vet[3] = (vet[3] == 0) ? 1 : 0;
		} else {
			puts("Erro no bit 2.");
			vet[1] = (vet[1] == 0) ? 1 : 0;
		}
	}

	/* Mostra depois de corrigido */
	puts("\nDepois de corrigir:");
	for (int i = 0; i < BITS_SIZE; i++) {
		printf("%d ", vet[i]);
	}
	puts("\n");

	return (0);

}
